{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "917eb069-b0e7-40c3-937c-3c74c727e654",
   "metadata": {},
   "source": [
    "### 导入模型库 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "92025ada-e825-4c04-9a0b-650bf45bb516",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings\n",
    "from llama_index.core.agent.workflow import AgentWorkflow\n",
    "from llama_index.embeddings.huggingface import HuggingFaceEmbedding\n",
    "import asyncio\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2401231b-49a1-4471-821f-23f4ab47c206",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 需要安装依赖llama-index-llms-huggingface\n",
    "!pip install llama-index-llms-huggingface"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3719074a-7ce2-489c-81c1-7c3a1d3b993c",
   "metadata": {},
   "source": [
    "### 加载模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "0f342167-2b6f-439d-8796-6ee1069010f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.llms.llama_cpp import LlamaCPP\n",
    "from transformers import AutoTokenizer\n",
    "\n",
    "# 加载本地模型\n",
    "tokenizer_model_id_or_path = r\"D:\\models\\Qwen\\Qwen2___5-7B-Instruct\"\n",
    "tokenizer = AutoTokenizer.from_pretrained(tokenizer_model_id_or_path)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "37ced1cb-eac3-4ffa-8570-e223ec8073b8",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "llama_model_loader: loaded meta data with 26 key-value pairs and 339 tensors from D:\\models\\Qwen\\Qwen2___5-7B-Instruct-GGUF\\qwen2.5-7b-instruct-q2_k.gguf (version GGUF V3 (latest))\n",
      "llama_model_loader: Dumping metadata keys/values. Note: KV overrides do not apply in this output.\n",
      "llama_model_loader: - kv   0:                       general.architecture str              = qwen2\n",
      "llama_model_loader: - kv   1:                               general.type str              = model\n",
      "llama_model_loader: - kv   2:                               general.name str              = qwen2.5-7b-instruct\n",
      "llama_model_loader: - kv   3:                            general.version str              = v0.1\n",
      "llama_model_loader: - kv   4:                           general.finetune str              = qwen2.5-7b-instruct\n",
      "llama_model_loader: - kv   5:                         general.size_label str              = 7.6B\n",
      "llama_model_loader: - kv   6:                          qwen2.block_count u32              = 28\n",
      "llama_model_loader: - kv   7:                       qwen2.context_length u32              = 131072\n",
      "llama_model_loader: - kv   8:                     qwen2.embedding_length u32              = 3584\n",
      "llama_model_loader: - kv   9:                  qwen2.feed_forward_length u32              = 18944\n",
      "llama_model_loader: - kv  10:                 qwen2.attention.head_count u32              = 28\n",
      "llama_model_loader: - kv  11:              qwen2.attention.head_count_kv u32              = 4\n",
      "llama_model_loader: - kv  12:                       qwen2.rope.freq_base f32              = 1000000.000000\n",
      "llama_model_loader: - kv  13:     qwen2.attention.layer_norm_rms_epsilon f32              = 0.000001\n",
      "llama_model_loader: - kv  14:                          general.file_type u32              = 10\n",
      "llama_model_loader: - kv  15:                       tokenizer.ggml.model str              = gpt2\n",
      "llama_model_loader: - kv  16:                         tokenizer.ggml.pre str              = qwen2\n",
      "llama_model_loader: - kv  17:                      tokenizer.ggml.tokens arr[str,152064]  = [\"!\", \"\\\"\", \"#\", \"$\", \"%\", \"&\", \"'\", ...\n",
      "llama_model_loader: - kv  18:                  tokenizer.ggml.token_type arr[i32,152064]  = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...\n",
      "llama_model_loader: - kv  19:                      tokenizer.ggml.merges arr[str,151387]  = [\"Ġ Ġ\", \"ĠĠ ĠĠ\", \"i n\", \"Ġ t\",...\n",
      "llama_model_loader: - kv  20:                tokenizer.ggml.eos_token_id u32              = 151645\n",
      "llama_model_loader: - kv  21:            tokenizer.ggml.padding_token_id u32              = 151643\n",
      "llama_model_loader: - kv  22:                tokenizer.ggml.bos_token_id u32              = 151643\n",
      "llama_model_loader: - kv  23:               tokenizer.ggml.add_bos_token bool             = false\n",
      "llama_model_loader: - kv  24:                    tokenizer.chat_template str              = {%- if tools %}\\n    {{- '<|im_start|>...\n",
      "llama_model_loader: - kv  25:               general.quantization_version u32              = 2\n",
      "llama_model_loader: - type  f32:  141 tensors\n",
      "llama_model_loader: - type q2_K:  113 tensors\n",
      "llama_model_loader: - type q3_K:   56 tensors\n",
      "llama_model_loader: - type q4_K:   28 tensors\n",
      "llama_model_loader: - type q6_K:    1 tensors\n",
      "llm_load_vocab: control token: 151661 '<|fim_suffix|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151649 '<|box_end|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151647 '<|object_ref_end|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151654 '<|vision_pad|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151659 '<|fim_prefix|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151648 '<|box_start|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151644 '<|im_start|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151646 '<|object_ref_start|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151650 '<|quad_start|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151651 '<|quad_end|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151652 '<|vision_start|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151653 '<|vision_end|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151655 '<|image_pad|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151656 '<|video_pad|>' is not marked as EOG\n",
      "llm_load_vocab: control token: 151660 '<|fim_middle|>' is not marked as EOG\n",
      "llm_load_vocab: special tokens cache size = 22\n",
      "llm_load_vocab: token to piece cache size = 0.9310 MB\n",
      "llm_load_print_meta: format           = GGUF V3 (latest)\n",
      "llm_load_print_meta: arch             = qwen2\n",
      "llm_load_print_meta: vocab type       = BPE\n",
      "llm_load_print_meta: n_vocab          = 152064\n",
      "llm_load_print_meta: n_merges         = 151387\n",
      "llm_load_print_meta: vocab_only       = 0\n",
      "llm_load_print_meta: n_ctx_train      = 131072\n",
      "llm_load_print_meta: n_embd           = 3584\n",
      "llm_load_print_meta: n_layer          = 28\n",
      "llm_load_print_meta: n_head           = 28\n",
      "llm_load_print_meta: n_head_kv        = 4\n",
      "llm_load_print_meta: n_rot            = 128\n",
      "llm_load_print_meta: n_swa            = 0\n",
      "llm_load_print_meta: n_embd_head_k    = 128\n",
      "llm_load_print_meta: n_embd_head_v    = 128\n",
      "llm_load_print_meta: n_gqa            = 7\n",
      "llm_load_print_meta: n_embd_k_gqa     = 512\n",
      "llm_load_print_meta: n_embd_v_gqa     = 512\n",
      "llm_load_print_meta: f_norm_eps       = 0.0e+00\n",
      "llm_load_print_meta: f_norm_rms_eps   = 1.0e-06\n",
      "llm_load_print_meta: f_clamp_kqv      = 0.0e+00\n",
      "llm_load_print_meta: f_max_alibi_bias = 0.0e+00\n",
      "llm_load_print_meta: f_logit_scale    = 0.0e+00\n",
      "llm_load_print_meta: n_ff             = 18944\n",
      "llm_load_print_meta: n_expert         = 0\n",
      "llm_load_print_meta: n_expert_used    = 0\n",
      "llm_load_print_meta: causal attn      = 1\n",
      "llm_load_print_meta: pooling type     = 0\n",
      "llm_load_print_meta: rope type        = 2\n",
      "llm_load_print_meta: rope scaling     = linear\n",
      "llm_load_print_meta: freq_base_train  = 1000000.0\n",
      "llm_load_print_meta: freq_scale_train = 1\n",
      "llm_load_print_meta: n_ctx_orig_yarn  = 131072\n",
      "llm_load_print_meta: rope_finetuned   = unknown\n",
      "llm_load_print_meta: ssm_d_conv       = 0\n",
      "llm_load_print_meta: ssm_d_inner      = 0\n",
      "llm_load_print_meta: ssm_d_state      = 0\n",
      "llm_load_print_meta: ssm_dt_rank      = 0\n",
      "llm_load_print_meta: ssm_dt_b_c_rms   = 0\n",
      "llm_load_print_meta: model type       = 7B\n",
      "llm_load_print_meta: model ftype      = Q2_K - Medium\n",
      "llm_load_print_meta: model params     = 7.62 B\n",
      "llm_load_print_meta: model size       = 2.80 GiB (3.16 BPW) \n",
      "llm_load_print_meta: general.name     = qwen2.5-7b-instruct\n",
      "llm_load_print_meta: BOS token        = 151643 '<|endoftext|>'\n",
      "llm_load_print_meta: EOS token        = 151645 '<|im_end|>'\n",
      "llm_load_print_meta: EOT token        = 151645 '<|im_end|>'\n",
      "llm_load_print_meta: PAD token        = 151643 '<|endoftext|>'\n",
      "llm_load_print_meta: LF token         = 148848 'ÄĬ'\n",
      "llm_load_print_meta: FIM PRE token    = 151659 '<|fim_prefix|>'\n",
      "llm_load_print_meta: FIM SUF token    = 151661 '<|fim_suffix|>'\n",
      "llm_load_print_meta: FIM MID token    = 151660 '<|fim_middle|>'\n",
      "llm_load_print_meta: FIM PAD token    = 151662 '<|fim_pad|>'\n",
      "llm_load_print_meta: FIM REP token    = 151663 '<|repo_name|>'\n",
      "llm_load_print_meta: FIM SEP token    = 151664 '<|file_sep|>'\n",
      "llm_load_print_meta: EOG token        = 151643 '<|endoftext|>'\n",
      "llm_load_print_meta: EOG token        = 151645 '<|im_end|>'\n",
      "llm_load_print_meta: EOG token        = 151662 '<|fim_pad|>'\n",
      "llm_load_print_meta: EOG token        = 151663 '<|repo_name|>'\n",
      "llm_load_print_meta: EOG token        = 151664 '<|file_sep|>'\n",
      "llm_load_print_meta: max token length = 256\n",
      "llm_load_tensors: tensor 'token_embd.weight' (q2_K) (and 338 others) cannot be used with preferred buffer type CPU_AARCH64, using CPU instead\n",
      "llm_load_tensors:   CPU_Mapped model buffer size =  2870.55 MiB\n",
      "..................................................................................\n",
      "llama_new_context_with_model: n_seq_max     = 1\n",
      "llama_new_context_with_model: n_ctx         = 3904\n",
      "llama_new_context_with_model: n_ctx_per_seq = 3904\n",
      "llama_new_context_with_model: n_batch       = 512\n",
      "llama_new_context_with_model: n_ubatch      = 512\n",
      "llama_new_context_with_model: flash_attn    = 0\n",
      "llama_new_context_with_model: freq_base     = 1000000.0\n",
      "llama_new_context_with_model: freq_scale    = 1\n",
      "llama_new_context_with_model: n_ctx_per_seq (3904) < n_ctx_train (131072) -- the full capacity of the model will not be utilized\n",
      "llama_kv_cache_init:        CPU KV buffer size =   213.50 MiB\n",
      "llama_new_context_with_model: KV self size  =  213.50 MiB, K (f16):  106.75 MiB, V (f16):  106.75 MiB\n",
      "llama_new_context_with_model:        CPU  output buffer size =     0.58 MiB\n",
      "llama_new_context_with_model:        CPU compute buffer size =   304.00 MiB\n",
      "llama_new_context_with_model: graph nodes  = 986\n",
      "llama_new_context_with_model: graph splits = 1\n",
      "AVX = 1 | AVX_VNNI = 0 | AVX2 = 1 | AVX512 = 0 | AVX512_VBMI = 0 | AVX512_VNNI = 0 | AVX512_BF16 = 0 | AMX_INT8 = 0 | FMA = 1 | NEON = 0 | SVE = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | RISCV_VECT = 0 | WASM_SIMD = 0 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | MATMUL_INT8 = 0 | LLAMAFILE = 1 | \n",
      "Model metadata: {'general.name': 'qwen2.5-7b-instruct', 'general.architecture': 'qwen2', 'general.type': 'model', 'general.finetune': 'qwen2.5-7b-instruct', 'general.version': 'v0.1', 'qwen2.block_count': '28', 'general.size_label': '7.6B', 'qwen2.context_length': '131072', 'qwen2.embedding_length': '3584', 'general.quantization_version': '2', 'tokenizer.ggml.bos_token_id': '151643', 'qwen2.feed_forward_length': '18944', 'qwen2.attention.head_count': '28', 'qwen2.attention.head_count_kv': '4', 'tokenizer.ggml.padding_token_id': '151643', 'qwen2.rope.freq_base': '1000000.000000', 'qwen2.attention.layer_norm_rms_epsilon': '0.000001', 'tokenizer.ggml.eos_token_id': '151645', 'general.file_type': '10', 'tokenizer.ggml.model': 'gpt2', 'tokenizer.ggml.pre': 'qwen2', 'tokenizer.ggml.add_bos_token': 'false', 'tokenizer.chat_template': '{%- if tools %}\\n    {{- \\'<|im_start|>system\\\\n\\' }}\\n    {%- if messages[0][\\'role\\'] == \\'system\\' %}\\n        {{- messages[0][\\'content\\'] }}\\n    {%- else %}\\n        {{- \\'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\\' }}\\n    {%- endif %}\\n    {{- \"\\\\n\\\\n# Tools\\\\n\\\\nYou may call one or more functions to assist with the user query.\\\\n\\\\nYou are provided with function signatures within <tools></tools> XML tags:\\\\n<tools>\" }}\\n    {%- for tool in tools %}\\n        {{- \"\\\\n\" }}\\n        {{- tool | tojson }}\\n    {%- endfor %}\\n    {{- \"\\\\n</tools>\\\\n\\\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\\\n<tool_call>\\\\n{{\\\\\"name\\\\\": <function-name>, \\\\\"arguments\\\\\": <args-json-object>}}\\\\n</tool_call><|im_end|>\\\\n\" }}\\n{%- else %}\\n    {%- if messages[0][\\'role\\'] == \\'system\\' %}\\n        {{- \\'<|im_start|>system\\\\n\\' + messages[0][\\'content\\'] + \\'<|im_end|>\\\\n\\' }}\\n    {%- else %}\\n        {{- \\'<|im_start|>system\\\\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\\\\n\\' }}\\n    {%- endif %}\\n{%- endif %}\\n{%- for message in messages %}\\n    {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) or (message.role == \"assistant\" and not message.tool_calls) %}\\n        {{- \\'<|im_start|>\\' + message.role + \\'\\\\n\\' + message.content + \\'<|im_end|>\\' + \\'\\\\n\\' }}\\n    {%- elif message.role == \"assistant\" %}\\n        {{- \\'<|im_start|>\\' + message.role }}\\n        {%- if message.content %}\\n            {{- \\'\\\\n\\' + message.content }}\\n        {%- endif %}\\n        {%- for tool_call in message.tool_calls %}\\n            {%- if tool_call.function is defined %}\\n                {%- set tool_call = tool_call.function %}\\n            {%- endif %}\\n            {{- \\'\\\\n<tool_call>\\\\n{\"name\": \"\\' }}\\n            {{- tool_call.name }}\\n            {{- \\'\", \"arguments\": \\' }}\\n            {{- tool_call.arguments | tojson }}\\n            {{- \\'}\\\\n</tool_call>\\' }}\\n        {%- endfor %}\\n        {{- \\'<|im_end|>\\\\n\\' }}\\n    {%- elif message.role == \"tool\" %}\\n        {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != \"tool\") %}\\n            {{- \\'<|im_start|>user\\' }}\\n        {%- endif %}\\n        {{- \\'\\\\n<tool_response>\\\\n\\' }}\\n        {{- message.content }}\\n        {{- \\'\\\\n</tool_response>\\' }}\\n        {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\\n            {{- \\'<|im_end|>\\\\n\\' }}\\n        {%- endif %}\\n    {%- endif %}\\n{%- endfor %}\\n{%- if add_generation_prompt %}\\n    {{- \\'<|im_start|>assistant\\\\n\\' }}\\n{%- endif %}\\n'}\n",
      "Available chat formats from metadata: chat_template.default\n",
      "Using gguf chat template: {%- if tools %}\n",
      "    {{- '<|im_start|>system\\n' }}\n",
      "    {%- if messages[0]['role'] == 'system' %}\n",
      "        {{- messages[0]['content'] }}\n",
      "    {%- else %}\n",
      "        {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}\n",
      "    {%- endif %}\n",
      "    {{- \"\\n\\n# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within <tools></tools> XML tags:\\n<tools>\" }}\n",
      "    {%- for tool in tools %}\n",
      "        {{- \"\\n\" }}\n",
      "        {{- tool | tojson }}\n",
      "    {%- endfor %}\n",
      "    {{- \"\\n</tools>\\n\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\n<tool_call>\\n{{\\\"name\\\": <function-name>, \\\"arguments\\\": <args-json-object>}}\\n</tool_call><|im_end|>\\n\" }}\n",
      "{%- else %}\n",
      "    {%- if messages[0]['role'] == 'system' %}\n",
      "        {{- '<|im_start|>system\\n' + messages[0]['content'] + '<|im_end|>\\n' }}\n",
      "    {%- else %}\n",
      "        {{- '<|im_start|>system\\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\\n' }}\n",
      "    {%- endif %}\n",
      "{%- endif %}\n",
      "{%- for message in messages %}\n",
      "    {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) or (message.role == \"assistant\" and not message.tool_calls) %}\n",
      "        {{- '<|im_start|>' + message.role + '\\n' + message.content + '<|im_end|>' + '\\n' }}\n",
      "    {%- elif message.role == \"assistant\" %}\n",
      "        {{- '<|im_start|>' + message.role }}\n",
      "        {%- if message.content %}\n",
      "            {{- '\\n' + message.content }}\n",
      "        {%- endif %}\n",
      "        {%- for tool_call in message.tool_calls %}\n",
      "            {%- if tool_call.function is defined %}\n",
      "                {%- set tool_call = tool_call.function %}\n",
      "            {%- endif %}\n",
      "            {{- '\\n<tool_call>\\n{\"name\": \"' }}\n",
      "            {{- tool_call.name }}\n",
      "            {{- '\", \"arguments\": ' }}\n",
      "            {{- tool_call.arguments | tojson }}\n",
      "            {{- '}\\n</tool_call>' }}\n",
      "        {%- endfor %}\n",
      "        {{- '<|im_end|>\\n' }}\n",
      "    {%- elif message.role == \"tool\" %}\n",
      "        {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != \"tool\") %}\n",
      "            {{- '<|im_start|>user' }}\n",
      "        {%- endif %}\n",
      "        {{- '\\n<tool_response>\\n' }}\n",
      "        {{- message.content }}\n",
      "        {{- '\\n</tool_response>' }}\n",
      "        {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n",
      "            {{- '<|im_end|>\\n' }}\n",
      "        {%- endif %}\n",
      "    {%- endif %}\n",
      "{%- endfor %}\n",
      "{%- if add_generation_prompt %}\n",
      "    {{- '<|im_start|>assistant\\n' }}\n",
      "{%- endif %}\n",
      "\n",
      "Using chat eos_token: <|im_end|>\n",
      "Using chat bos_token: <|endoftext|>\n"
     ]
    }
   ],
   "source": [
    "model_path = r\"D:\\models\\Qwen\\Qwen2___5-7B-Instruct-GGUF\\qwen2.5-7b-instruct-q2_k.gguf\"\n",
    "\n",
    "llm = LlamaCPP(\n",
    "    # You can pass in the URL to a GGML model to download it automatically\n",
    "    model_url=None,\n",
    "    # optionally, you can set the path to a pre-downloaded model instead of model_url\n",
    "    model_path=model_path,\n",
    "    temperature=0.1,\n",
    "    max_new_tokens=512,\n",
    "    verbose=True,\n",
    ")\n",
    "Settings.llm = llm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "970e5e7d-62e2-439e-b2a3-9f76b589a951",
   "metadata": {},
   "source": [
    "## 接下来，使用增强检索"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "242c4e93-0cd6-4d22-b15f-21690d5ecc3e",
   "metadata": {},
   "source": [
    "### 使用set_global_tokenizer配置分词模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "4dc0a0a4-70fd-4953-ac01-4270c9503e93",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import set_global_tokenizer\n",
    "from transformers import AutoTokenizer\n",
    "\n",
    "tokenizer_model_id_or_path = r\"D:\\models\\Qwen\\Qwen2___5-7B-Instruct\"\n",
    "set_global_tokenizer(\n",
    "    AutoTokenizer.from_pretrained(tokenizer_model_id_or_path).encode\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7734a6a4-b008-45f0-9057-1b1bcc83e3ec",
   "metadata": {},
   "source": [
    "### 使用HuggingFaceEmbedding配置embed模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "e2dd90ae-8fe9-4d0b-87b4-17387f38ea53",
   "metadata": {},
   "outputs": [],
   "source": [
    "# use Huggingface embeddings\n",
    "from llama_index.embeddings.huggingface import HuggingFaceEmbedding\n",
    "\n",
    "embed_model_path = r\"D:\\models\\BAAI\\bge-m3\"\n",
    "embed_model = HuggingFaceEmbedding(model_name=embed_model_path)\n",
    "Settings.embed_model = embed_model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ee2bbea-1eb8-4a83-8980-95e00b89858e",
   "metadata": {},
   "source": [
    "### 加载PDF"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b8282943-90f7-4749-b945-c900f74ac86c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import SimpleDirectoryReader\n",
    "\n",
    "# load documents\n",
    "documents = SimpleDirectoryReader(\"./data\").load_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "92e6ace2-2c28-4666-b73e-0e3a4338e52f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "文档 ID: f0bdb90d-8d56-43d4-b034-b67c9b9b77f0\n",
      "文档内容: P/N: 147003835\n",
      "© 版权所有 联想 2010\n",
      "Lenovo\n",
      "安全及通用信息指南\n",
      "www.lenovo.com.cn\n",
      "New World. New Thinking.\n",
      "TM\n",
      "--------------------------------------------------\n",
      "文档 ID: 3e213a66-efd1-485e-9542-356cb529519e\n",
      "文档内容: \n",
      "--------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 查看文档内容\n",
    "for doc in documents[:2]:\n",
    "    print(f\"文档 ID: {doc.doc_id}\")\n",
    "    print(f\"文档内容: {doc.text}\")\n",
    "    print(\"-\" * 50)  # 分隔不同的文档"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "754372e8-ca3e-40dc-906e-6106ebad5947",
   "metadata": {},
   "source": [
    "### 生成向量引擎"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "037e3ea2-d6a7-4693-9600-89c299c53c2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import VectorStoreIndex\n",
    "\n",
    "# create vector store index\n",
    "index = VectorStoreIndex.from_documents(documents)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "410936a7-6191-4258-bfac-020ab336cfd9",
   "metadata": {},
   "source": [
    "### 输出检索结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "01cb9358-9b6a-4e32-b23d-de430d90f0c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建检索器\n",
    "retriever = index.as_retriever(\n",
    "    similarity_top_k=3,  # 返回最相似的3个文档\n",
    "    search_kwargs={\"score_threshold\": 0.7},# 相似度阈值,\n",
    "    document_content_description=\"关于联想电脑的产品说明书\", # 文档内容描述\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "34d34643-4bd4-41e8-b2d4-fe96d78c9f57",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Llama.generate: 790 prefix-match hit, remaining 1 prompt tokens to eval\n",
      "llama_perf_context_print:        load time =  171441.40 ms\n",
      "llama_perf_context_print: prompt eval time =       0.00 ms /     1 tokens (    0.00 ms per token,      inf tokens per second)\n",
      "llama_perf_context_print:        eval time =       0.00 ms /   512 runs   (    0.00 ms per token,      inf tokens per second)\n",
      "llama_perf_context_print:       total time =  214333.11 ms /   513 tokens\n"
     ]
    }
   ],
   "source": [
    "# 直接使用查询引擎获取答案\n",
    "query_engine = index.as_query_engine()\n",
    "response = query_engine.query(\"如果我在柬埔寨、印度尼西亚、菲律宾、越南或斯里兰卡,我需要注意什么？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "b03b0405-6608-45df-9d51-37eba4e52d39",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. 如果在柬埔寨、印度尼西亚、菲律宾、越南或斯里兰卡获得软件产品，则由本软件产品引起或与之相关的争议应通过在新加坡进行的仲裁最终解决。\n",
      "2. 本协议将受新加坡法律管辖，并根据该法解释和强制执行，而不考虑其法律冲突规则。 如果您在印度获得软件产品，则由本软件产品引起的或与之相关的争议应通过在印度班加罗尔进行的仲裁予以最终解决。\n",
      "3. 在新加坡进行的仲裁将依据新加坡国际仲裁中心当时有效的仲裁规则（“SIAC规则”）进行。在印度进行的仲裁将依据印度当时有效的法律进行。仲裁裁决应为终局的并对双方有约束力（不得上诉），并且裁决应以书面形式作出并阐明事实认定和法律结论。所有仲裁程序，包括在该仲裁程序中出示的所有文件，均采用英语；本协议的英文版在此仲裁程序中优先于任何其他语言的版本。 4. 请勿将电池丢入掩埋处理的垃圾中。处理电池时，请遵照当地的法令或法规。应该以室温存储电池，并且将其充电到30%到50%。建议每年对电池充电一次以防止过量放电。 5. 如果使用未经授权的电池，系统将继续启动，但可能不会对电池充电。 6. 请勿将电池投入或浸入水中。请按照当地法令或法规要求处理电池。 7. 请勿将电池加热至超过100℃（212℉）。 8. 请勿修理或拆开电池。 9. 请勿将电池置于儿童无法触及之处。 10. 请勿跌落电池。 11. 请勿将电池丢入掩埋处理的垃圾中。处理电池时，请遵照当地的法令或法规。应该以室温存储电池，并且将其充电到30%到50%。建议每年对电池充电一次以防止过量放电。 12. 本系统不支持除联想制造或联想授权制造的正品电池之外的其他电池。如果使用未经授权的电池，系统将继续启动，但可能不会对电池充电。 13. 如果更换纽扣锂电池时操作不当会有爆炸危险。更换纽扣锂电池时，请仅使用相同的电池或制造商推荐的同类电池。锂电池含有锂，如果使用、\n"
     ]
    }
   ],
   "source": [
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "1a2d06df-aa5a-49f2-9517-1923da61447d",
   "metadata": {},
   "outputs": [],
   "source": [
    "#  或者执行检索\n",
    "nodes = retriever.retrieve(\"如果我在柬埔寨、印度尼西亚、菲律宾、越南或斯里兰卡,我需要注意什么？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28b04a56-1bbe-4c55-963b-d48406384a97",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(nodes)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
